package com.wyw.learning.thread.flowcontrol.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 演示Condition的基本用法
 *
 * Condition的作用
 *  当线程1需要等待某个条件的时候，它就去执行condition.await()方法，一旦执行了await()方法，线程就会进入阻塞状态
 *  然后通常会有另外一个线程，假设是线程2，去执行对应的条件，直到这个条件达成时，线程2就会去执行condition.signal()方法，这是JVM就会从被阻塞的线程中找，找到那些等候该condition的线程，当线程1就会收到可执行信号的时候，他的线程状态就会编程Runnable可执行状态
 *
 * signalAll()和signal()区别
 *  signalAll()会唤起所有的正在等待的线程
 *  signal是公平的，只会唤起等待时间最长的线程
 *
 * Condition注意点
 *  实际上，如果说Lock用来代替synchronized,那么Condition就是用来代替响应的Object.wait/notifu的，所以在用法和性质上，几乎一致
 *  await方法会自动释放持有的Lock锁，和Object.wait一样，不需要自己手动释放锁
 *  调用await的时候，必须尺有所，否则会抛出异常，和Object.wait一样
 *
 *
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
public class ConditionDemo1 {
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();//绑定在锁上

    void method1() throws InterruptedException {
        lock.lock();
        try{
            System.out.println("条件不满足，开始await");
            condition.await();//这里会释放锁，会改变锁行为
            System.out.println("条件满足了，开始执行后续的任务");
        }finally {
            System.out.println("method1释放锁");
            lock.unlock();
        }
    }

    void method2() {
        lock.lock();
        try{
            System.out.println("准备工作完成，唤醒其他的线程");
            condition.signal();
        }finally {
            System.out.println("method2释放锁");
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ConditionDemo1 conditionDemo1 = new ConditionDemo1();
        new Thread(new Runnable() {//新线程，因为如果都在main线程，流程会卡死
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    conditionDemo1.method2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        conditionDemo1.method1();
    }

}
